#!/usr/bin/python
"""
Threading exercise.

Starts and stops new thread on demand.

The thread keeps printing something while the user is allowed to start/stop
the printing by typing 1 or 0


This script also contains a function that reads a single keypress, which
seems to be non-trivial to be implemented cross-platform.

"""

import threading
import time


def read_single_keypress():
    """Waits for a single keypress on stdin.

    This is a silly function to call if you need to do it a lot because it has
    to store stdin's current setup, setup stdin for reading single keystrokes
    then read the single keystroke then revert stdin back after reading the
    keystroke.

    Returns the character of the key that was pressed (zero on
    KeyboardInterrupt which can happen when a signal gets handled)

    """
    import termios, fcntl, sys, os
    fd = sys.stdin.fileno()
    # save old state
    flags_save = fcntl.fcntl(fd, fcntl.F_GETFL)
    attrs_save = termios.tcgetattr(fd)
    # make raw - the way to do this comes from the termios(3) man page.
    attrs = list(attrs_save) # copy the stored version to update
    # iflag
    attrs[0] &= ~(termios.IGNBRK | termios.BRKINT | termios.PARMRK 
                  | termios.ISTRIP | termios.INLCR | termios. IGNCR 
                  | termios.ICRNL | termios.IXON )
    # oflag
    attrs[1] &= ~termios.OPOST
    # cflag
    attrs[2] &= ~(termios.CSIZE | termios. PARENB)
    attrs[2] |= termios.CS8
    # lflag
    attrs[3] &= ~(termios.ECHONL | termios.ECHO | termios.ICANON
                  | termios.ISIG | termios.IEXTEN)
    termios.tcsetattr(fd, termios.TCSANOW, attrs)
    # turn off non-blocking
    fcntl.fcntl(fd, fcntl.F_SETFL, flags_save & ~os.O_NONBLOCK)
    # read a single keystroke
    try:
        ret = sys.stdin.read(1) # returns a single character
    except KeyboardInterrupt: 
        ret = 0
    finally:
        # restore old state
        termios.tcsetattr(fd, termios.TCSAFLUSH, attrs_save)
        fcntl.fcntl(fd, fcntl.F_SETFL, flags_save)
    return ret
    
    
    
class Doer(threading.Thread):
    counter = 0
    bRunning = False
    bFirst = True
    bFinish = False
    
    def run(self):
        while True:
            if self.bFinish:
                break
            if self.bRunning:
                print "Counter is %d" % self.counter
                self.counter += 1

            time.sleep(1.618)
        
    def Start(self):
        """This can be called several times, as opposed to start() (lowercase S)"""
        print "Started"
        self.bRunning = True
        if self.bFirst:
            self.start()
            print "First time, eh"
            self.bFirst = False
        
    def Stop(self):
        print "Stopped"
        self.bRunning = False
        
    def Finish(self):
        self.bFinish = True

doer = Doer()

while True:
    print "Please press \"1\" to start, \"0\" to stop, \"2\" to exit"
    k = read_single_keypress()
    print k
    if k == "0":
        doer.Stop()
    elif k == "1":
        doer.Start()
    elif k == "2":
        doer.Finish()
        break
